﻿/**
 * Copyright (c) 2008 Justin Etheredge http://www.codethinked.com
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Microsoft Public License (Ms-PL)
 * which accompanies this distribution, and is available at
 * http://www.opensource.org/licenses/ms-pl.html
 * If redistributing this code, this entire header must remain intact.
 * 
 * Some of the code in this application has been taken 
 * from the following sources (all of which are licensed under
 * the Ms-PL):
 * Matt Warren's Blog: http://blogs.msdn.com/mattwar/
 * MSDN: http://msdn2.microsoft.com/en-us/library/bb546158.aspx
 */

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using LinqToSimpleDB;
using System.Threading;

namespace LinqToSimpleDBTest
{
  /// <summary>
  /// Summary description for PopulateDataTest
  /// </summary>
  [TestClass]
  public class PopulateDataTest
  {
    public PopulateDataTest()
    {
    }

    private TestContext testContextInstance;

    /// <summary>
    ///Gets or sets the test context which provides
    ///information about and functionality for the current test run.
    ///</summary>
    public TestContext TestContext
    {
      get
      {
        return testContextInstance;
      }
      set
      {
        testContextInstance = value;
      }
    }

    #region Additional test attributes
    //
    // You can use the following additional attributes as you write your tests:
    //
    // Use ClassInitialize to run code before running the first test in the class
    [ClassInitialize()]
    public static void MyClassInitialize(TestContext testContext) 
    {
      SimpleDBContext.SetAccessKeys(TestSetup.awsAccessKey, TestSetup.awsSecretKey);
    }
    #endregion

    //need more tests with numbers and whatnot
    //  also make sure to put in tests with negative numbers

    [TestMethod]
    public void CreateListAndDeleteDomainTest()
    {
      if (!TestSetup.UseMockClient)
      {
        string domainName = "TestDomain";
        List<string> domains = null;
        bool domainFound = false;
        SimpleDBContext.CreateDomain(domainName);
        try
        {
          domains = SimpleDBContext.ListDomains();
          foreach (string domain in domains)
          {
            if (domain == domainName)
            {
              domainFound = true;
            }
          }
          Assert.IsTrue(domainFound);
        }
        finally
        {
          SimpleDBContext.DeleteDomain("TestDomain");
        }

        domains = SimpleDBContext.ListDomains();
        domainFound = false;
        foreach (string domain in domains)
        {
          if (domain == domainName)
          {
            domainFound = true;
          }
        }
        Assert.IsFalse(domainFound);
      }
    }

    [TestMethod]
    public void PopulateAndQueryDataTest()
    {
      if (!TestSetup.UseMockClient)
      {
        SimpleDBContext.CreateDomain("TestDomain");
        LinqToSimpleDB.SimpleDBContext context = TestSetup.GetContext("TestDomain");
        try
        {
          var item = new LinqToSimpleDB.SimpleDBItem("test1")
            .WithAttribute(new LinqToSimpleDB.SimpleDBAttribute("attrib1", "value1", "value2"))
            .WithAttribute(new LinqToSimpleDB.SimpleDBAttribute("attrib2", "value3", "value4"));
          context.AddItem(item);

          item = new LinqToSimpleDB.SimpleDBItem("test2")
            .WithAttribute(new LinqToSimpleDB.SimpleDBAttribute("attrib1", "value1", "value3"))
            .WithAttribute(new LinqToSimpleDB.SimpleDBAttribute("attrib2", "value3", "value5"));
          context.AddItem(item);

          context.SubmitChanges();

          System.Threading.Thread.Sleep(2000);

          var items = from p in context.Domain where p.Attributes["attrib1"] == "value1" select p;

          List<LinqToSimpleDB.SimpleDBItem> itemsList = items.ToList();
          Assert.IsTrue(itemsList.Count == 2);

          foreach (LinqToSimpleDB.SimpleDBItem queriedItem in itemsList)
          {
            Assert.IsTrue(queriedItem.Name == "test1" || queriedItem.Name == "test2");
          }
        }
        finally
        {
          SimpleDBContext.DeleteDomain("TestDomain");
        }
      }
    }

    [TestMethod]
    public void PopulateAndDeleteDataTest()
    {
      if (!TestSetup.UseMockClient)
      {
        SimpleDBContext.CreateDomain("TestDomain");
        LinqToSimpleDB.SimpleDBContext context = TestSetup.GetContext("TestDomain");
        try
        {
          var item = new LinqToSimpleDB.SimpleDBItem("test1")
            .WithAttribute(new LinqToSimpleDB.SimpleDBAttribute("attrib1", "value1", "value2"))
            .WithAttribute(new LinqToSimpleDB.SimpleDBAttribute("attrib2", "value3", "value4"));
          context.AddItem(item);
          Assert.IsFalse(item.IsSaved);
          context.SubmitChanges();
          Assert.IsTrue(item.IsSaved);

          System.Threading.Thread.Sleep(2000);

          var items = from p in context.Domain 
            where p.Attributes["attrib1"] == "value1" select p;

          List<LinqToSimpleDB.SimpleDBItem> itemsList = items.ToList();
          Assert.IsTrue(itemsList.Count == 1);

          foreach (LinqToSimpleDB.SimpleDBItem queriedItem in itemsList)
          {
            Assert.IsTrue(queriedItem.IsSaved);
            Assert.IsTrue(queriedItem.Name == "test1");
            Assert.IsTrue(queriedItem.Attributes.Count == 2);
          }

          item.Attributes["attrib1"].Delete();
          context.SubmitChanges();

          System.Threading.Thread.Sleep(30000);

          items = from p in context.Domain
            where p.Attributes["attrib1"] == "value1" select p;

          itemsList = items.ToList();
          Assert.IsTrue(itemsList.Count == 0, "Actual {0} Expected {1}", itemsList.Count, 0);

          items = from p in context.Domain 
            where p.Attributes["attrib2"] == "value3" select p;

          itemsList = items.ToList();
          Assert.IsTrue(itemsList.Count == 1);
        }
        finally
        {
          SimpleDBContext.DeleteDomain("TestDomain");
        }
      }
    }

    [TestMethod]
    public void PopulateNumbersTest()
    {
      if (!TestSetup.UseMockClient)
      {
        SimpleDBContext.CreateDomain("TestDomain");
        LinqToSimpleDB.SimpleDBContext context = TestSetup.GetContext("TestDomain");
        try
        {
          var item = new LinqToSimpleDB.SimpleDBItem("test1")
                  .WithAttribute("attrib1", "35")
                  .WithAttribute("attrib2", "12.2")
                  .WithAttribute("attrib3", "15.00002");
          context.AddItem(item);

          var item2 = new LinqToSimpleDB.SimpleDBItem("test2")
                  .WithAttribute("attrib1", "25");
          context.AddItem(item2);

          var item3 = new LinqToSimpleDB.SimpleDBItem("test3")
                  .WithAttribute("attrib1", "21");
          context.AddItem(item3);

          Assert.IsFalse(item.IsSaved);
          context.SubmitChanges();
          Assert.IsTrue(item.IsSaved);

          Thread.Sleep(5000);
          
          var p = from g in context.Domain where g.Attributes["attrib1"] == 35 select g;
          List<SimpleDBItem> itemsList = p.ToList();
          Assert.IsTrue(itemsList.Count == 1);

          p = from g in context.Domain where g.Attributes["attrib1"] > 23 select g;
          itemsList = p.ToList();
          Assert.IsTrue(itemsList.Count == 2);

          p = from g in context.Domain where g.Attributes["attrib1"] > 26 select g;
          itemsList = p.ToList();
          Assert.IsTrue(itemsList.Count == 1);

          p = from g in context.Domain where g.Attributes["attrib1"] < 36 select g;
          itemsList = p.ToList();
          Assert.IsTrue(itemsList.Count == 3);
        }
        finally
        {
          SimpleDBContext.DeleteDomain("TestDomain");
        }
      }
    }

    [TestMethod]
    public void SelectByNameTest()
    {
      if (!TestSetup.UseMockClient)
      {
        SimpleDBContext.CreateDomain("TestDomain");
        LinqToSimpleDB.SimpleDBContext context = TestSetup.GetContext("TestDomain");
        try
        {
          var item = new LinqToSimpleDB.SimpleDBItem("test1")
                  .WithAttribute(new LinqToSimpleDB.SimpleDBAttribute("attrib1", "35"));
          context.AddItem(item);
          Assert.IsFalse(item.IsSaved);
          context.SubmitChanges();
          Assert.IsTrue(item.IsSaved);

          string testvalue = "test1";
          var p = from g in context.Domain 
                  where g.Name == testvalue select g;

          Thread.Sleep(3000);

          List<SimpleDBItem> itemsList = p.ToList();
          Assert.IsTrue(itemsList.Count == 1);
        }
        finally
        {
          SimpleDBContext.DeleteDomain("TestDomain");
        }
      }
    }
  }
}
